package com.cloud.freeflow.api.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cloud.freeflow.api.bean.WfActDef;
import com.cloud.freeflow.api.bean.WfActPart;
import com.cloud.freeflow.api.entity.BizType;
import com.cloud.freeflow.api.entity.ProcActDef;
import com.cloud.freeflow.api.entity.ProcDef;
import com.cloud.freeflow.api.entity.ProcPart;
import com.cloud.freeflow.api.entity.ProcTransDef;
import com.cloud.freeflow.api.mapper.BizTypeMapper;
import com.cloud.freeflow.api.mapper.ProcActDefMapper;
import com.cloud.freeflow.api.mapper.ProcActPartMapper;
import com.cloud.freeflow.api.mapper.ProcDefMapper;
import com.cloud.freeflow.api.mapper.ProcTransDefMapper;
import com.cloud.freeflow.api.service.FreeflowInterfaceService;
import com.cloud.freeflow.api.service.ProcDefService;
import com.cloud.freeflow.api.service.ProcPartService;

import tk.mybatis.mapper.entity.Example;

@Service
@Transactional
public class FreeflowInterfaceServiceImpl implements FreeflowInterfaceService {

	@Autowired
	private BizTypeMapper bizTypeMapper;
	
	@Autowired
	private ProcDefService procDefService;

	@Autowired
	private ProcPartService procPartService;

	@Autowired
	private ProcActDefMapper procActDefMapper;

	@Autowired
	private ProcActPartMapper procActPartMapper;

	@Autowired
	private ProcDefMapper procDefMapper;

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Autowired
	private ProcTransDefMapper procTransDefMapper;

	@Override
	public List<ProcDef> listProcDefs(Long bizId) {
		return procDefService.listProcDefs(bizId);
	}

	@Override
	public List<ProcPart> listActParts(Long actDefId) {
		return procPartService.listActSelectedParts(actDefId);
	}

	@Override
	public List<ProcPart> listProcParts(long id) {
		return procPartService.listProcParts(id);
	}

	@Override
	public List<ProcDef> loadProcActParts(long bizId) {
		List<ProcDef> procs = procDefService.listProcDefs(bizId);
		for (ProcDef proc : procs) {
			Example actExample = new Example(ProcActDef.class);
			Example.Criteria actCriteria = actExample.createCriteria();
			actCriteria.andEqualTo("procDefId", proc.getProcDefId());
			actCriteria.andEqualTo("deleteFlag", 0);
			List<ProcActDef> actDefs = procActDefMapper.selectByExample(actExample);
			for (ProcActDef actDef : actDefs) {
				List<ProcPart> parts = procActPartMapper.listActSelectedParts(proc.getProcDefId(),
						actDef.getActDefId());
				actDef.setActParts(parts);
			}
			proc.setActDefs(actDefs);
		}
		return procs;
	}

	@Override
	public WfActDef loadStartActByProcAndPart(long procDefId, String parts) {
		List<ProcActDef> startActs = jdbcTemplate.query(
				"select * from proc_act_def t1 where t1.proc_def_id = ? and t1.act_def_attr_id & 2 = 2 and "
						+ "t1.delete_flag = 0 and exists (select * from proc_act_part t2 where t2.part_id in(" + parts
						+ ") and t1.act_def_id = t2.act_def_id) ",
				new BeanPropertyRowMapper<ProcActDef>(ProcActDef.class), procDefId);
		if (null == startActs || startActs.size() == 0) {
			return null;
		}
		// 存在多个时，取第一个
		ProcActDef start = startActs.get(0);
		WfActDef result = new WfActDef();
		BeanUtils.copyProperties(start, result);
		ProcDef procDef = procDefMapper.selectByPrimaryKey(procDefId);
		result.setBizId(procDef.getBizId());
		result.setBizName(procDef.getBizName());
		result.setProcDefName(procDef.getProcDefName());
		result.setTimeStrategy(procDef.getTimeStrategy());
		result.setTimeUnitId(procDef.getTimeUnitId());
		result.setProcTimeWarn(procDef.getTimeWarn());
		result.setProcTimeLimit(procDef.getTimeLimit());
		return result;
	}

	@Override
	public List<WfActDef> searchNextActDefs(Long actDefId) {
		Example transExample = new Example(ProcTransDef.class);
		Example.Criteria transCriteria = transExample.createCriteria();
		transCriteria.andEqualTo("fromAct", actDefId);
		transCriteria.andEqualTo("deleteFlag", 0);
		List<ProcTransDef> trans = procTransDefMapper.selectByExample(transExample);
		// 获取下个环节的节点
		List<WfActDef> results = new ArrayList<WfActDef>();
		for (ProcTransDef tran : trans) {
			ProcActDef actDef = procActDefMapper.selectByPrimaryKey(tran.getToAct());
			WfActDef wd = new WfActDef();
			wd.setTransDefId(tran.getTransId());
			BeanUtils.copyProperties(actDef, wd);
			wd.setTransFilterSql(tran.getFilterSql());// 流向过滤
			List<WfActPart> parts = procActPartMapper.listWfActPartByActDefId(tran.getProcDefId(), tran.getToAct());
			wd.setParts(parts);
			results.add(wd);
		}
		return results;
	}

	@Override
	public WfActDef loadActDefById(long actDefId) {
		ProcActDef actDef = procActDefMapper.selectByPrimaryKey(actDefId);
		// 存在多个时，取第一个
		WfActDef result = new WfActDef();
		BeanUtils.copyProperties(actDef, result);
		ProcDef procDef = procDefMapper.selectByPrimaryKey(actDef.getProcDefId());
		result.setBizId(procDef.getBizId());
		result.setBizName(procDef.getBizName());
		result.setProcDefName(procDef.getProcDefName());
		result.setTimeStrategy(procDef.getTimeStrategy());
		result.setTimeUnitId(procDef.getTimeUnitId());
		result.setProcTimeWarn(procDef.getTimeWarn());
		result.setProcTimeLimit(procDef.getTimeLimit());
		return result;
	}

	@Override
	public List<WfActDef> loadActDefByProc(Long procDefId) {
		Example exp = new Example(ProcActDef.class);
		Example.Criteria criteria = exp.createCriteria();
		criteria.andEqualTo("procDefId", procDefId);
		criteria.andEqualTo("deleteFlag", 0);
		List<ProcActDef> acts = procActDefMapper.selectByExample(exp);
		List<WfActDef> results = new ArrayList<WfActDef>();
		for(ProcActDef actDef : acts){
			WfActDef act = new WfActDef();
			BeanUtils.copyProperties(actDef, act);
			List<WfActPart> parts = procActPartMapper.listWfActPartByActDefId(procDefId, act.getActDefId());
			act.setParts(parts);
			results.add(act);
		}
		return results;
	}

	@Override
	public List<BizType> listCustomBizType() {
		Example example = new Example(BizType.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("customFlag", 1);
		return bizTypeMapper.selectByExample(example);
	}

	@Override
	public Long createCustomBiz(Integer bizId, String bizName) {
		//创建业务
		Date now = new Date();
		BizType bizType = new BizType();
		bizType.setBizId(bizId.longValue());
		bizType.setCreateTime(now);
		bizType.setCustomFlag(1);
		bizType.setDeleteFlag(0);
		bizType.setDisplayOrder(bizId);
		bizType.setBizName(bizName);
		bizTypeMapper.insert(bizType);
		//创建默认流程
		ProcDef procDef = new ProcDef();
		procDef.setProcDefName(bizName);
		procDef.setBizId(bizId.longValue());
		procDef.setBizName(bizName);
		procDef.setCreateTime(now);
		procDef.setDeleteFlag(0);
		procDefMapper.insert(procDef);
		return procDef.getProcDefId();
	}

}
